home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Demo / threads / bug.py next >
Text File  |  1996-03-11  |  2KB  |  70 lines

  1. # The following self-contained little program usually freezes with most
  2. # threads reporting
  3. # Unhandled exception in thread:
  4. # Traceback (innermost last):
  5. #   File "importbug.py", line 6
  6. #     x = whrandom.randint(1,3)
  7. # AttributeError: randint
  8. # Here's the program; it doesn't use anything from the attached module:
  9.  
  10. import thread
  11.  
  12. def task():
  13.     global N
  14.     import whrandom
  15.     x = whrandom.randint(1,3)
  16.     a.acquire()
  17.     N = N - 1
  18.     if N == 0: done.release()
  19.     a.release()
  20.  
  21. a = thread.allocate_lock()
  22. done = thread.allocate_lock()
  23. N = 10
  24.  
  25. done.acquire()
  26. for i in range(N):
  27.     thread.start_new_thread(task, ())
  28. done.acquire()
  29. print 'done'
  30.  
  31.  
  32. # Sticking an acquire/release pair around the 'import' statement makes the
  33. # problem go away.
  34. # I believe that what happens is:
  35. # 1) The first thread to hit the import atomically reaches, and executes
  36. #    most of, get_module.  In particular, it finds Lib/whrandom.pyc,
  37. #    installs its name in sys.modules, and executes
  38. #         v = eval_code(co, d, d, d, (object *)NULL);
  39. #    to initialize the module.
  40. # 2) eval_code "ticker"-slices the 1st thread out, and gives another thread
  41. #    a chance.  When this 2nd thread hits the same 'import', import_module
  42. #    finds 'whrandom' in sys.modules, so just proceeds.
  43. # 3) But the 1st thread is still "in the middle" of executing whrandom.pyc.
  44. #    So the 2nd thread has a good chance of trying to look up 'randint'
  45. #    before the 1st thread has placed it in whrandom's dict.
  46. # 4) The more threads there are, the more likely that at least one of them
  47. #    will do this before the 1st thread finishes the import work.
  48. # If that's right, a perhaps not-too-bad workaround would be to introduce a
  49. # static "you can't interrupt this thread" flag in ceval.c, check it before
  50. # giving up interpreter_lock, and have IMPORT_NAME set it & restore (plain
  51. # clearing would not work) it around its call to import_module.  To its
  52. # credit, there's something wonderfully perverse about fixing a race via an
  53. # unprotected static <grin>.
  54. # as-with-most-other-things-(pseudo-)parallel-programming's-more-fun-
  55. #    in-python-too!-ly y'rs  - tim
  56. # Tim Peters   tim@ksr.com
  57. # not speaking for Kendall Square Research Corp
  58.